package com.voyage.generator.service.impl;

import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.voyage.generator.entity.CodeConfig;
import com.voyage.generator.mapper.ColumnInfoRepository;
import com.voyage.generator.mapper.GenConfigRepository;
import com.voyage.generator.model.ColumnInfo;
import com.voyage.generator.model.PrincipleMO;
import com.voyage.generator.model.TableInfo;
import com.voyage.generator.service.GeneratorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @Author: kangb on 2021/10/9 19:06
 * @param:
 * @return:
 * @Description:
 */
@Service
@Slf4j
public class GeneratorServiceImpl implements GeneratorService {


    private ColumnInfoRepository columnInfoRepository;
    private GenConfigRepository genConfigRepository;
    private Environment environment;

    @Autowired
    public GeneratorServiceImpl(ColumnInfoRepository columnInfoRepository,
                                GenConfigRepository genConfigRepository,
                                Environment environment) {
        this.columnInfoRepository = columnInfoRepository;
        this.genConfigRepository = genConfigRepository;
        this.environment = environment;
    }


    @Override
    public boolean async() {
        //获取所有表的元数据信息
        List<TableInfo> allTables = genConfigRepository.getAllTableInfo();
        allTables.forEach(e -> {
            CodeConfig codeConfig = new CodeConfig();
            BeanUtils.copyProperties(e, codeConfig);
            genConfigRepository.insert(codeConfig);
        });
        return true;
    }

    @Override
    public List<ColumnInfo> list(String tableName) {
        return genConfigRepository.getColumnsByTableName(tableName);
    }

    @Override
    public boolean execute(PrincipleMO principleMO) {
        AutoGenerator generator = new AutoGenerator();

        //全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        globalConfig.setOutputDir(projectPath + "/" + principleMO.getModuleName() + "/src/main/java");
        globalConfig.setFileOverride(true);
        globalConfig.setActiveRecord(true);
        globalConfig.setEnableCache(false);
        globalConfig.setBaseColumnList(true);
        globalConfig.setBaseColumnList(true);
        globalConfig.setOpen(false);
        globalConfig.setAuthor(principleMO.getAuthor());
        globalConfig.setEntityName(principleMO.getApiAlias() + "DO");
        globalConfig.setControllerName(principleMO.getApiAlias() + "Controller");
        globalConfig.setServiceName(principleMO.getApiAlias() + "Service");
        globalConfig.setServiceImplName(principleMO.getApiAlias() + "ServiceImpl");
        globalConfig.setMapperName(principleMO.getApiAlias() + "Repository");
        globalConfig.setSwagger2(true);
        globalConfig.setIdType(IdType.ID_WORKER);
        generator.setGlobalConfig(globalConfig);

        //设置数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl(environment.getProperty("spring.datasource.druid.url"));
        dataSourceConfig.setUsername(environment.getProperty("spring.datasource.druid.username"));
        dataSourceConfig.setPassword(environment.getProperty("spring.datasource.druid.password"));
        dataSourceConfig.setDriverName(environment.getProperty("spring.datasource.druid.driver-class-name"));
        dataSourceConfig.setDbType(DbType.MYSQL);
        generator.setDataSource(dataSourceConfig);

        //包的设置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent(principleMO.getPack());
        packageConfig.setController("controller");
        packageConfig.setService("service");
        packageConfig.setServiceImpl("service.impl");
        packageConfig.setMapper("mapper");
        packageConfig.setEntity("entity");
        generator.setPackageInfo(packageConfig);

        //策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityClass("com.voyage.common.constant.BaseDO");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setSuperControllerClass("BaseController");
        strategy.setSuperEntityColumns("id");
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setInclude(principleMO.getTableName());
        strategy.setLogicDeleteFieldName("deleted");
        TableFill createdTimeFill = new TableFill("createTime", FieldFill.INSERT);
        TableFill updatedTimeFill = new TableFill("updateTime", FieldFill.INSERT_UPDATE);
        List<TableFill> list = new ArrayList<>();
        list.add(createdTimeFill);
        list.add(updatedTimeFill);
        strategy.setTableFillList(list);
        strategy.setVersionFieldName("version");
        strategy.setControllerMappingHyphenStyle(true);

        generator.setStrategy(strategy);

        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                //自定义参数设置,使用cfg.instance获取
                HashMap<String, Object> map = new HashMap<>();
                String first = principleMO.getApiAlias().substring(0, 1);
                String second = principleMO.getApiAlias().substring(1);
                map.put("instance", first.toLowerCase() + second);
                setMap(map);
            }
        };
        generator.setCfg(injectionConfig);

        //关闭默认xml生成，改成自定义配置
        //generator.setTemplateEngine(new FreemarkerTemplateEngine());
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setEntity("/templates/entity.java.vm");
        templateConfig.setController("/templates/controller.java.vm");
        templateConfig.setService("/templates/service.java.vm");
        templateConfig.setServiceImpl("/templates/serviceImpl.java.vm");
        templateConfig.setMapper("/templates/mapper.java.vm");
        generator.setTemplate(templateConfig);

        generator.execute();
        log.info("代码生成成功");
        ZipUtil.zip(projectPath + "/" + principleMO.getModuleName());
        log.info("代码压缩成功");
        //todo 上传至第三方服务器,删除本地文件

        return true;
    }

}
